﻿using System;
using System.Reflection;
using System.Xml.Linq;
using Phoenix.Xna.Framework.Xml;

namespace Phoenix.Xna.Framework.Serialization.Markup.Properties
{
    /// <summary>
    /// The markup information for a value property.
    /// </summary>
    internal class ValueMarkupProperty : MarkupPropertyBase<object>
    {
        #region IMarkupElement Members

        /// <summary>
        /// Serialize the element to XML.
        /// </summary>
        /// <returns>The element markup serialzed as an XElement.</returns>
        public override XElement Serialize()
        {
            XElement element = new XElement(NamespaceCache.GetNamespaceFor(ObjectType) + ObjectType.Name, _value);
            element.SetAttribute(AttributeIDs.PropertyIDAttribute, Name);
            return element;
        }

        /// <summary>
        /// Deserialize the element from an XElement.
        /// </summary>
        /// <param name="element">The XElement to deserialize this element from.</param>
        public override void Deserialize(XElement element)
        {
            ObjectType = NamespaceCache.GetType(element.Name.LocalName, element.Name.Namespace);

            if (element != null)
            {
                Name = element.ReadAttribute<string>(AttributeIDs.PropertyIDAttribute);
                _value = element.Value;
            }
        }

        #endregion

        #region IMarkupProperty Members 

        /// <summary>
        /// Extract the markup information from the PropertyInfo for this property.
        /// </summary>
        /// <param name="field">The PropertyInfo for this property.</param>
        /// <param name="value">The value of the property.</param>
        public override void ExtractMarkup(PropertyInfo property, object value)
        {
            ObjectType = property.PropertyType;
            Name = property.Name;
            ShouldPersist = SerializablePropertyAttribute.ShouldPersist(property, value);

            if (ShouldPersist)
            {
                _value = value;
            }
        }

        /// <summary>
        /// Sets the value of MarkupProperty to the instance's property value.
        /// </summary>
        /// <param name="instance">The instance to set the property on.</param>
        public override void SetValue(object instance)
        {
            PropertyInfo property = instance.GetType().GetProperty(Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static);
            property.SetValue(instance, _value.TypeConvertionCast(property.PropertyType), null);
        }

        #endregion       
    }
}